package com.ideaaedi.springcloud.jd.commonspring.support;

import com.ideaaedi.extspringcache.annotation.ExtCacheable;
import com.ideaaedi.extspringcache.annotation.Redis;
import com.ideaaedi.springcloud.jd.commonds.constant.BaseConstant;
import com.ideaaedi.springcloud.jd.commonds.entity.BaseCodeMsgEnum;
import com.ideaaedi.springcloud.jd.commonds.entity.Result;
import com.ideaaedi.springcloud.jd.commonds.entity.user.bo.ApiInfoBO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.resp.SysDataScopeDetailRespVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.resp.SysUserDetailRespVO;
import com.ideaaedi.springcloud.jd.commonds.enums.CachePrefixEnum;
import com.ideaaedi.springcloud.jd.commonds.enums.SpecUserTenantEnum;
import com.ideaaedi.springcloud.jd.commonds.exception.BaseException;
import com.ideaaedi.springcloud.jd.commonspring.config.ExtRedisSerializerConfig;
import com.ideaaedi.springcloud.jd.commonspring.feignclient.OauthFeignClient;
import com.ideaaedi.springcloud.jd.commonspring.util.JdContextUtil;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;

import javax.annotation.Resource;
import java.time.temporal.ChronoUnit;
import java.util.LinkedHashSet;
import java.util.Objects;

/**
 * 通用service
 *
 * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img
 * src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
 * @since 2021.0.1.E
 */
@EnableCaching
@Configuration
@SuppressWarnings("SpringCacheNamesInspection")
public class AuthService {
    
    @Resource
    protected OauthFeignClient oauthFeignClient;
    
    /**
     * 查询用户所属租户
     *
     * @param userId 用户id
     * @param cachePrefixEnum 缓存前缀枚举，请使用{@link CachePrefixEnum#AC_USER_TENANT}
     *
     * @return 用户所属租户
     */
    @ExtCacheable(cacheNames = BaseConstant.CACHE_NAMES, key = "#cachePrefixEnum.keyWithoutCacheName(#userId)",
            redis = @Redis(useRedisTemplate = BaseConstant.REDIS_TEMPLATE_NAME,
                    timeUnit = ChronoUnit.DAYS
            )
    )
    public String queryUserTenant(@NonNull CachePrefixEnum cachePrefixEnum, @NonNull Long userId) {
        Objects.requireNonNull(cachePrefixEnum, "cachePrefixEnum cannot be null.");
        Objects.requireNonNull(userId, "userId cannot be null.");
        Result<SysUserDetailRespVO> result;
        Pair<Pair<Long, String>, Pair<String, String>> pairPair = null;
        try {
            pairPair = JdContextUtil.clearAndGet();
            JdContextUtil.settingUserIdAndTenantIfMiss(SpecUserTenantEnum.SYSTEM_READ_ACCESS_CONTROL_DATA);
            result = oauthFeignClient.sysUserDetail(userId);
        } finally {
            if (pairPair != null) {
                JdContextUtil.clear(SpecUserTenantEnum.SYSTEM_READ_ACCESS_CONTROL_DATA);
                JdContextUtil.settingUserIdAndTenantIfMiss(
                        pairPair.getLeft().getLeft(), pairPair.getLeft().getRight(),
                        pairPair.getRight().getLeft(), pairPair.getRight().getRight()
                );
            }
        }
        if (!BaseCodeMsgEnum.SUCCESS.code().equals(result.getCode())) {
            throw new BaseException(result);
        }
        return result.getData().getTenant();
    }
    
    /**
     * 查询用户直接拥有的所有api简讯
     *
     * @param userId 要查询数据的用户id
     * @param cachePrefixEnum 缓存前缀枚举，请使用{@link CachePrefixEnum#AC_USER_API}
     *
     * @return 用户直接拥有的所有api简讯
     */
    @ExtCacheable(cacheNames = BaseConstant.CACHE_NAMES, key = "#cachePrefixEnum.keyWithoutCacheName(#userId)",
            redis = @Redis(useRedisTemplate = BaseConstant.REDIS_TEMPLATE_NAME,
                    timeUnit = ChronoUnit.DAYS
            )
    )
    public LinkedHashSet<ApiInfoBO> queryUserApi(@NonNull CachePrefixEnum cachePrefixEnum, @NonNull Long userId) {
        Objects.requireNonNull(cachePrefixEnum, "cachePrefixEnum cannot be null.");
        Objects.requireNonNull(userId, "userId cannot be null.");
        Result<LinkedHashSet<ApiInfoBO>> result;
        Pair<Pair<Long, String>, Pair<String, String>> pairPair = null;
        try {
            pairPair = JdContextUtil.clearAndGet();
            JdContextUtil.settingUserIdAndTenantIfMiss(SpecUserTenantEnum.SYSTEM_READ_ACCESS_CONTROL_DATA);
            result = oauthFeignClient.sysUserListUserApi(userId);
        } finally {
            if (pairPair != null) {
                JdContextUtil.clear(SpecUserTenantEnum.SYSTEM_READ_ACCESS_CONTROL_DATA);
                JdContextUtil.settingUserIdAndTenantIfMiss(
                        pairPair.getLeft().getLeft(), pairPair.getLeft().getRight(),
                        pairPair.getRight().getLeft(), pairPair.getRight().getRight()
                );
            }
        }
        if (!BaseCodeMsgEnum.SUCCESS.code().equals(result.getCode())) {
            throw new BaseException(result);
        }
        return result.getData();
    }
    
    /**
     * 查用户数据权限
     *
     * @param userId 用户id
     * @param cachePrefixEnum 缓存前缀枚举，请使用{@link CachePrefixEnum#AC_USER_DATA_SCOPE}
     *
     * @return 查用户数据权限
     */
    @ExtCacheable(cacheNames = BaseConstant.CACHE_NAMES, key = "#cachePrefixEnum.keyWithoutCacheName(#userId)",
            redis = @Redis(useRedisTemplate = BaseConstant.REDIS_TEMPLATE_NAME,
                    timeUnit = ChronoUnit.DAYS
            )
    )
    public SysDataScopeDetailRespVO queryUserDataScope(@NonNull CachePrefixEnum cachePrefixEnum, @NonNull Long userId) {
        Objects.requireNonNull(cachePrefixEnum, "cachePrefixEnum cannot be null.");
        Objects.requireNonNull(userId, "userId cannot be null.");
        Result<SysDataScopeDetailRespVO> result;
        Pair<Pair<Long, String>, Pair<String, String>> pairPair = null;
        try {
            pairPair = JdContextUtil.clearAndGet();
            JdContextUtil.settingUserIdAndTenantIfMiss(SpecUserTenantEnum.SYSTEM_READ_ACCESS_CONTROL_DATA);
            result = oauthFeignClient.sysDataScopeDetailByUserId(userId);
        } finally {
            if (pairPair != null) {
                JdContextUtil.clear(SpecUserTenantEnum.SYSTEM_READ_ACCESS_CONTROL_DATA);
                JdContextUtil.settingUserIdAndTenantIfMiss(
                        pairPair.getLeft().getLeft(), pairPair.getLeft().getRight(),
                        pairPair.getRight().getLeft(), pairPair.getRight().getRight()
                );
            }
        }
        if (!BaseCodeMsgEnum.SUCCESS.code().equals(result.getCode())) {
            throw new BaseException(result);
        }
        return result.getData();
    }
}
